﻿using N_m3u8DL_RE.Common.Entity;
using N_m3u8DL_RE.Common.Log;
using N_m3u8DL_RE.Common.Resource;
using N_m3u8DL_RE.Entity;
using System.Text.RegularExpressions;

namespace N_m3u8DL_RE.Util;

public static class FilterUtil
{
    public static List<StreamSpec> DoFilterKeep(IEnumerable<StreamSpec> lists, StreamFilter? filter)
    {
        if (filter == null) return [];

        var inputs = lists.Where(_ => true);
        if (filter.GroupIdReg != null)
            inputs = inputs.Where(i => i.GroupId != null && filter.GroupIdReg.IsMatch(i.GroupId));
        if (filter.LanguageReg != null)
            inputs = inputs.Where(i => i.Language != null && filter.LanguageReg.IsMatch(i.Language));
        if (filter.NameReg != null)
            inputs = inputs.Where(i => i.Name != null && filter.NameReg.IsMatch(i.Name));
        if (filter.CodecsReg != null)
            inputs = inputs.Where(i => i.Codecs != null && filter.CodecsReg.IsMatch(i.Codecs));
        if (filter.ResolutionReg != null)
            inputs = inputs.Where(i => i.Resolution != null && filter.ResolutionReg.IsMatch(i.Resolution));
        if (filter.FrameRateReg != null)
            inputs = inputs.Where(i => i.FrameRate != null && filter.FrameRateReg.IsMatch($"{i.FrameRate}"));
        if (filter.ChannelsReg != null)
            inputs = inputs.Where(i => i.Channels != null && filter.ChannelsReg.IsMatch(i.Channels));
        if (filter.VideoRangeReg != null)
            inputs = inputs.Where(i => i.VideoRange != null && filter.VideoRangeReg.IsMatch(i.VideoRange));
        if (filter.UrlReg != null)
            inputs = inputs.Where(i => i.Url != null && filter.UrlReg.IsMatch(i.Url));
        if (filter.SegmentsMaxCount != null && inputs.All(i => i.SegmentsCount > 0)) 
            inputs = inputs.Where(i => i.SegmentsCount < filter.SegmentsMaxCount);
        if (filter.SegmentsMinCount != null && inputs.All(i => i.SegmentsCount > 0))
            inputs = inputs.Where(i => i.SegmentsCount > filter.SegmentsMinCount);
        if (filter.PlaylistMinDur != null)
            inputs = inputs.Where(i => i.Playlist?.TotalDuration > filter.PlaylistMinDur);
        if (filter.PlaylistMaxDur != null)
            inputs = inputs.Where(i => i.Playlist?.TotalDuration < filter.PlaylistMaxDur);
        if (filter.BandwidthMin != null)
            inputs = inputs.Where(i => i.Bandwidth >= filter.BandwidthMin);
        if (filter.BandwidthMax != null)
            inputs = inputs.Where(i => i.Bandwidth <= filter.BandwidthMax);
        if (filter.Role.HasValue)
            inputs = inputs.Where(i => i.Role == filter.Role);

        var bestNumberStr = filter.For.Replace("best", "");
        var worstNumberStr = filter.For.Replace("worst", "");

        if (filter.For == "best" && inputs.Any())
            inputs = inputs.Take(1).ToList();
        else if (filter.For == "worst" && inputs.Any())
            inputs = inputs.TakeLast(1).ToList();
        else if (int.TryParse(bestNumberStr, out int bestNumber) && inputs.Any())
            inputs = inputs.Take(bestNumber).ToList();
        else if (int.TryParse(worstNumberStr, out int worstNumber) && inputs.Any())
            inputs = inputs.TakeLast(worstNumber).ToList();

        return inputs.ToList();
    }

    public static List<StreamSpec> DoFilterDrop(IEnumerable<StreamSpec> lists, StreamFilter? filter)
    {
        if (filter == null) return [.. lists];

        var inputs = lists.Where(_ => true);
        var selected = DoFilterKeep(lists, filter);

        inputs = inputs.Where(i => selected.All(s => s.ToString() != i.ToString()));

        return inputs.ToList();
    }

    public static List<StreamSpec> SelectStreams(IEnumerable<StreamSpec> lists)
    {
        var streamSpecs = lists.ToList();
        return streamSpecs;
        
        //// 基本流
        //var basicStreams = streamSpecs.Where(x => x.MediaType == null).ToList();
        //// 可选音频轨道
        //var audios = streamSpecs.Where(x => x.MediaType == MediaType.AUDIO).ToList();
        //// 可选字幕轨道
        //var subs = streamSpecs.Where(x => x.MediaType == MediaType.SUBTITLES).ToList();

        //var prompt = new MultiSelectionPrompt<StreamSpec>()
        //        .Title(ResString.promptTitle)
        //        .UseConverter(x =>
        //        {
        //            if (x.Name != null && x.Name.StartsWith("__"))
        //                return $"[darkslategray1]{x.Name[2..]}[/]";
        //            return x.ToString().EscapeMarkup().RemoveMarkup();
        //        })
        //        .Required()
        //        .PageSize(10)
        //        .MoreChoicesText(ResString.promptChoiceText)
        //        .InstructionsText(ResString.promptInfo)
        //    ;

        //// 默认选中第一个
        //var first = streamSpecs.First();
        //prompt.Select(first);

        //if (basicStreams.Count != 0)
        //{
        //    prompt.AddChoiceGroup(new StreamSpec() { Name = "__Basic" }, basicStreams);
        //}

        //if (audios.Count != 0)
        //{
        //    prompt.AddChoiceGroup(new StreamSpec() { Name = "__Audio" }, audios);
        //    // 默认音轨
        //    if (first.AudioId != null)
        //    {
        //        prompt.Select(audios.First(a => a.GroupId == first.AudioId));
        //    }
        //}
        //if (subs.Any())
        //{
        //    prompt.AddChoiceGroup(new StreamSpec() { Name = "__Subtitle" }, subs);
        //    // 默认字幕轨
        //    if (first.SubtitleId != null)
        //    {
        //        prompt.Select(subs.First(s => s.GroupId == first.SubtitleId));
        //    }
        //}

        //// 如果此时还是没有选中任何流，自动选择一个
        //prompt.Select(basicStreams.Concat(audios).Concat(subs).First());

        //// 多选
        //var selectedStreams = CustomAnsiConsole.Console.Prompt(prompt);

        //return selectedStreams;
    }

    /// <summary>
    /// 根据用户输入，清除广告分片
    /// </summary>
    /// <param name="selectedSteams"></param>
    /// <param name="keywords"></param>
    public static void CleanAd(List<StreamSpec> selectedSteams, string[]? keywords)
    {
        if (keywords == null) return;
        var regList = keywords.Select(s => new Regex(s)).ToList();
        foreach ( var reg in regList)
        {
            Logger.Info($"{ResString.customAdKeywordsFound}[Cyan underline]{reg}");
        }

        foreach (var stream in selectedSteams)
        {
            if (stream.Playlist == null) continue;

            var countBefore = stream.SegmentsCount;

            foreach (var part in stream.Playlist.MediaParts)
            {
                // 没有找到广告分片
                if (part.MediaSegments.All(x => regList.All(reg => !reg.IsMatch(x.Url))))
                {
                    continue;
                }
                // 找到广告分片 清理
                part.MediaSegments = part.MediaSegments.Where(x => regList.All(reg => !reg.IsMatch(x.Url))).ToList();
            }

            // 清理已经为空的 part
            stream.Playlist.MediaParts = stream.Playlist.MediaParts.Where(x => x.MediaSegments.Count > 0).ToList();

            var countAfter = stream.SegmentsCount;

            if (countBefore != countAfter)
            {
                Logger.Warn("{} segments => {} segments", countBefore, countAfter);
            }
        }
    }
}